/**
 * Copyright 2012 Brigham Young University
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package edu.byu.nlp.cluster;

import java.util.Collection;

import com.google.common.collect.Collections2;

import edu.byu.nlp.data.SparseFeatureVector;
import edu.byu.nlp.pipes.Instance;
import edu.byu.nlp.pipes.Instances;
import edu.byu.nlp.util.Collections3;

/**
 * @author rah67
 *
 */
public class Datasets {

	private Datasets() { }
	
	// Combines the labeled and unlabeled Collections into a single view over the whole data.
	public static Collection<SparseFeatureVector> allData(Dataset data) {
		return Collections3.concat(unlabel(data.labeledData()), data.unlabeledData());
	}
	
	public static <L, D> Collection<D> unlabel(Collection<Instance<L, D>> labeled) {
		return Collections2.transform(labeled, Instances.<L, D>dataExtractor());
	}
	
	/** Sums the counts of each feature in both the labeled and unlabeled data **/
	public static double[] countFeatures(Dataset data) {
		return countFeatures(allData(data), data.getNumFeatures());
	}
	
	public static double[] countFeaturesInLabeledData(Dataset data) {
		return countFeatures(unlabel(data.labeledData()), data.getNumFeatures());
	}
	
	public static double[] countFeaturesInUnlabeledData(Dataset data) {
		return countFeatures(data.unlabeledData(), data.getNumFeatures());
	}

	public static double[] countFeatures(Iterable<SparseFeatureVector> it, int numFeatures) {
		double[] featureCounts = new double[numFeatures];
		for (SparseFeatureVector instance : it) {
			instance.addTo(featureCounts);
		}
		return featureCounts;
	}

	public static double[][] countLabelsAndFeatures(Dataset data) {
		return countLabelsAndFeatures(data.labeledData(), data.getNumLabels(), data.getNumFeatures());
	}
	
	public static double[][] countLabelsAndFeatures(Iterable<Instance<Integer, SparseFeatureVector>> it,
			int numLabels, int numFeatures) {
		double[][] featureCounts = new double[numLabels][numFeatures];
		for (Instance<Integer, SparseFeatureVector> instance : it) {
			instance.getData().addTo(featureCounts[instance.getLabel()]);
		}
		return featureCounts;
	}

	public static double[] countLabels(Dataset data) {
		// FIXME : doesn't work for clustering
		return countLabels(data.labeledData(), data.getNumLabels());
	}
	
	public static double[] countLabels(Iterable<Instance<Integer, SparseFeatureVector>> it, int numLabels) {
		double[] counts = new double[numLabels];
		for (Instance<Integer, SparseFeatureVector> i : it) {
			++counts[i.getLabel()];
		}
		return counts;
	}

}
